/*
 * Copyright (c) 2015. For Intelligent Group.
 */

package com.intelligent.ispc.core.service.impl;

import com.google.common.collect.Lists;
import com.intelligent.ispc.common.mapper.BeanMapper;
import com.intelligent.ispc.core.dto.DataDictionaryDto;
import com.intelligent.ispc.core.entity.DataDictionary;
import com.intelligent.ispc.core.repository.jpa.DataDictionaryDao;
import com.intelligent.ispc.core.service.DataDictionaryService;
import com.intelligent.ispc.utils.DDCategory;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.*;
import java.util.List;
import java.util.Map;

/**
 * Created by Peter.Li on 2015/10/30.
 */
@Service
public class DataDictionaryServiceImpl implements DataDictionaryService {
    private static Logger logger = LoggerFactory.getLogger(DataDictionaryServiceImpl.class);

    @Autowired
    private DataDictionaryDao dataDictionaryDao;

    @Override
    public List<DataDictionaryDto> findByCategoryAndParent(DDCategory ddCategory, String parentId) {

        Specification<DataDictionary> spec = new Specification<DataDictionary>() {
            public Predicate toPredicate(Root<DataDictionary> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Join<DataDictionary, DataDictionary> leftJoin = root.join(root.getModel().getSingularAttribute("parent", DataDictionary.class), JoinType.LEFT);

                List<Predicate> predicates = Lists.newArrayList();
                Predicate predicate = cb.equal(root.get("category").as(DDCategory.class), ddCategory);
                predicates.add(predicate);

                if (StringUtils.isNotBlank(parentId)) {
                    Predicate p = cb.equal(leftJoin.get("id").as(String.class), parentId);
                    predicates.add(p);
                } else {
                    Predicate p = cb.isNull(leftJoin.get("id").as(String.class));
                    predicates.add(p);
                }

                if (!predicates.isEmpty()) {
                    query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
                }

                return query.getRestriction();
            }
        };

        List<DataDictionary> list = dataDictionaryDao.findAll(spec);
        List<DataDictionaryDto> dtos = Lists.newArrayList();
        dtos = BeanMapper.mapList(list, DataDictionaryDto.class);

        return dtos;
    }


    @Override
    public List<DataDictionary> findByCategoryAndParent(DDCategory ddCategory, Map<String, Object> paramMap, String parentId) {

        Specification<DataDictionary> spec = new Specification<DataDictionary>() {
            public Predicate toPredicate(Root<DataDictionary> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Join<DataDictionary, DataDictionary> leftJoin = root.join(root.getModel().getSingularAttribute("parent", DataDictionary.class), JoinType.LEFT);

                List<Predicate> predicates = Lists.newArrayList();
                Predicate predicate = cb.equal(root.get("category").as(DDCategory.class), ddCategory);
                predicates.add(predicate);

                if (paramMap.containsKey("attributeName") && paramMap.get("attributeName") != null) {
                    Predicate p = cb.equal(root.get("attributeName").as(String.class), paramMap.get("attributeName"));
                    predicates.add(p);
                }
                if (StringUtils.isNotBlank(parentId)) {
                    Predicate p = cb.equal(leftJoin.get("id").as(String.class), parentId);
                    predicates.add(p);
                }

                if (!predicates.isEmpty()) {
                    query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
                }

                return query.getRestriction();
            }
        };

        List<DataDictionary> list = dataDictionaryDao.findAll(spec);
        return list;
    }
}
